[org 0x7c00]

;清屏
mov ax,3
int 0x10

;初始化段寄存器
mov ax,0
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0x7c00


mov si, booting
call print


mov edi,0x1000  ;读取目标内存
mov ecx,2       ;起始扇区
mov bl, 4       ;扇区数量

call read_disk


cmp word [0x1000],0x55aa
jnz error
jmp 0:0x1002

;阻塞
jmp $

read_disk:
    ;设置读写扇区的数量
    mov dx,0x1f2
    mov al,bl
    out dx,al

    inc dx      ;0x1f3
    mov al,cl   ;起始扇区的0 ~ 7位
    out dx,al
    
    inc dx      ;0x1f4
    shr ecx,8
    mov al,cl   ;起始扇区的8 ~ 15位
    out dx,al
    
    inc dx      ;0x1f5
    shr ecx,8
    mov al,cl   ;起始扇区的16 ~ 23位
    out dx,al
    
    inc dx      ;0x1f6
    shr ecx,8
    and cl,0b1111;起始扇区的24 ~ 27位

    mov al,0b1110_0000 ;主盘 LBA模式
    or al,cl
    out dx,al
    
    inc dx          ;0x1f7
    mov al,0x20     ;读硬盘
    out dx,al
    
    xor ecx,ecx
    mov cl,bl      ;得到读写扇区的数量

    .read:
        push cx
        call .waits;等待数据准备完毕
        call .reads;读取一个扇区
        pop cx
        loop .read
    ret

    .waits:
        mov dx,0x1f7
        .check:
            in al,dx
            jmp $+2;直接跳转下一行 类似于 nop 但相对于 nop 消耗时钟周期更多
            jmp $+2
            jmp $+2
            and al,0b1000_1000
            cmp al,0b0000_1000
            jnz .check
        ret
    
    .reads:
        mov dx,0x1f0
        mov cx,256
        .readw:
            in ax,dx
            jmp $+2
            jmp $+2
            jmp $+2
            mov [edi],ax
            add edi,2
            loop .readw
        ret
        
print:
    mov ah,0x0e
    .next:
        mov al, [si]
        cmp al,0
        jz .done
        int 0x10
        inc si
        jmp .next
    .done:
    ret

booting:
    db "Booting MyOs..", 10, 13, 0 ;  10:\n   13:\r


error:
    mov si,.msg
    call print
    hlt             ;cpu 进入省电模式
    jmp $
    .msg db "Booting Error!!!", 10, 13, 0

times 510-($-$$) db 0
;dw 0xaa55
db 0x55,0xaa